#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<poll.h>
#include<fcntl.h>
#include<errno.h>
#include<arpa/inet.h>
#include<netinet/in.h>
//#include<sys/socket.h>
#include<sys/types.h>

const int SIZE = 256;
int main() {
  // 创建套接字并且进行异常预防处理；
  int lfd = socket(AF_INET,SOCK_STREAM,0);
  if (lfd<0) {
    perror("socket build failed!");
    exit(-1);
  }
  
  // 设置IO端口多路复用；
  int opt=1;
  int ret = setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
  if (ret<0) {
    perror("setsocket failed;");
    close(lfd);
    exit(-1);
  }
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(8888);
  inet_pton(AF_INET,"127.0.0.1",&addr.sin_addr);
  // 初始化网络地址结构体；
  ret = bind(lfd,(struct sockaddr*)&addr,sizeof(addr));
  if (ret<0) {
    perror("socket bind failed, please check your socket addr");
    close(lfd);
    exit(-1);
  } 
  ret = listen(lfd,256);
  if (ret<0) {
    perror("listen error;");
    close(lfd);
    exit(-1);
  }
  struct pollfd ev[SIZE];
  ev[0].fd = lfd;
  ev[0].events = POLLIN;
  for(int i=1;i<SIZE;++i){
    ev[i].fd = -1;
  }
  int maxfd = 0;
  int nready=0,cfd;
  char buf[1024];
  printf("服务启动\n");
  while(1){
        
    nready = poll(ev,maxfd+1,-1);
    if(nready>0){
        if(ev[0].revents & POLLIN){
            cfd = accept(lfd,NULL,NULL);
            if(cfd<0){
                if(errno==EINTR||errno==ECONNABORTED){
                    perror("连接终止\n");
                    continue;
                }
                break;
            }
            int flag = fcntl(cfd,F_GETFL);
            flag |=O_NONBLOCK;
            fcntl(cfd,F_SETFL,flag);
            int i=1;
            for(;i<SIZE;++i){
                if(ev[i].fd<0){
                    ev[i].fd = cfd;
                    break;
                }
            }
            if(i==SIZE){
                printf("连接过多\n");
                continue;
            }
            ev[i].events = POLLIN;
            if(i>maxfd) maxfd = i;
            if(--nready<=0) continue;

        }
        for(int i=1;i<=maxfd;++i){
            if(ev[i].fd<0) continue;
            int n;
            if(ev[i].revents&POLLIN){
                memset(buf,0x00,sizeof(buf));
                n = read(ev[i].fd,buf,sizeof(buf)-1);
                if(n<0){
                    close(ev[i].fd);
                    ev[i].fd = -1;
                    perror("read error");
                }else if(0==n){
                    printf("close the fd=[%d]\n",ev[i].fd);
                    close(ev[i].fd);
                    ev[i].fd = -1;
                }else{
                    printf("client sendmsg: %s\n",buf);
                }
            }
            if(--nready<=0) break;
        }
    }
  }
  close(lfd);
  return 0;
}